<template>
  <div>
    <Header></Header>
    <Navigator></Navigator>
    <div id="body">
      <h2>贪吃蛇</h2>
      <div id="main">

        <div id="game"></div>

        <div id="score">
          <div id="score_text">得分</div>
          <div id="score_num">{{score}}</div>
          <div id="speed_num">{{1000 - speed}}</div>
          <el-slider v-model="speedBase"></el-slider>
          <el-button type="primary" @click="start">开始</el-button>
        </div>

      </div>
    </div>
  </div>
</template>

<script>
import Header from "@/components/Header.vue";
import Navigator from "@/components/Navigator.vue";

export default {
  name: "Snake",
  components: {Navigator, Header},
  data() {
    return {
      score: 0,
      snake: [],
      food: [],
      direction: 'down',
      speed: 300,
      isOver: false,
      speedBase: 70,
    }
  },
  methods: {
    init() {
      this.score = 0;
      this.snake = [
        {x: 0, y: 2},
        {x: 0, y: 1},
        {x: 0, y: 0},
      ];
      this.food = {x: 10, y: 10};
      this.direction = 'down';
      this.speed = 1000 - this.speedBase * 10;
      this.isOver = false;
      this.timer = null;
    },

    start() {
      // clear all Interval
      clearInterval(this.timer);

      // start a new game
      this.init();
      this.createFood();
      this.printSnake()
      this.move();
    },

    printSnake(){
      console.log("printSnake")
      // clear snake in #game
      const snake = document.getElementById('game');
      snake.innerHTML = '';

      // print snake in #game
      for (let i = 1; i < this.snake.length; i++) {
        const snakeBody = document.createElement('div');
        snakeBody.id = 'snake_body';
        // absolute position
        snakeBody.style.position = 'absolute';
        snakeBody.style.left = this.snake[i].x * 20 + 'px';
        snakeBody.style.top = this.snake[i].y * 20 + 'px';
        snakeBody.style.width = '20px';
        snakeBody.style.height = '20px';
        // color black, the shorter the snake, the darker
        if (this.snake.length <= 5){
          snakeBody.style.backgroundColor = 'rgb(' + (200 - 20 * i) + ','
              + (200 - 20 * i) + ',' + (200 - 20 * i) + ')';
        }
        else if (this.snake.length <= 10){
          snakeBody.style.backgroundColor = 'rgb(' + (200 - 20 * i) + ','
              + (0) + ',' + (200 - 20 * i) + ')';
        }
        else if (this.snake.length <= 15){
          snakeBody.style.backgroundColor = 'rgb(' + (200 - 20 * i) + ','
              + (200 - 20 * i) + ',' + (0) + ')';
        }
        else{
          snakeBody.style.backgroundColor = 'rgb(' + (0) + ','
              + (200 - 20 * i) + ',' + (200 - 20 * i) + ')';
        }

        snake.appendChild(snakeBody);
      }

      const food = document.createElement('div');
      food.id = 'food';
      // absolute position
      food.style.position = 'absolute';
      food.style.left = this.food.x * 20 + 'px';
      food.style.top = this.food.y * 20 + 'px';
      food.style.width = '20px';
      food.style.height = '20px';
      // color random
      food.style.backgroundColor = 'rgb(' + (Math.floor(Math.random() * 256)) + ','
          + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ')';
      // round
      food.style.borderRadius = '40%';

      snake.appendChild(food);

      const snakeHead = document.createElement('div');
      snakeHead.id = 'snake_head';
      // absolute position
      snakeHead.style.position = 'absolute';
      snakeHead.style.left = this.snake[0].x * 20 + 'px';
      snakeHead.style.top = this.snake[0].y * 20 + 'px';
      snakeHead.style.width = '20px';
      snakeHead.style.height = '20px';
      // color red
      snakeHead.style.backgroundColor = 'red';
      snake.appendChild(snakeHead);

    },

    move() {
      this.timer = setInterval(() => {
        if (this.isOver) {
          clearInterval(this.timer);
          return;
        }
        this.snakeMove();
        this.isEat();
        this.printSnake();
        this.isDead();
      }, this.speed);
    },

    snakeMove() {
      const head = this.snake[0];
      const newHead = {x: head.x, y: head.y};
      switch (this.direction) {
        case 'left':
          newHead.x--;
          break;
        case 'right':
          newHead.x++;
          break;
        case 'up':
          newHead.y--;
          break;
        case 'down':
          newHead.y++;
          break;
      }
      // append newHead to the first of snake
      this.snake.unshift(newHead);
      // pop the last of snake
      this.snake.pop();
      console.log("snakeMove:", this.snake[0].x, this.snake[0].y);
    },

    isEat() {
      const head = this.snake[0];
      let isEat = false;
      switch (this.direction){
        case 'left':
          if (head.x - 1 === this.food.x && head.y === this.food.y) {
            isEat = true;
          }
          break;
        case 'right':
          if (head.x + 1 === this.food.x && head.y === this.food.y) {
            isEat = true;
          }
          break;
        case 'up':
          if (head.x === this.food.x && head.y - 1 === this.food.y) {
            isEat = true;
          }
          break;
        case 'down':
          if (head.x === this.food.x && head.y + 1 === this.food.y) {
            isEat = true;
          }
          break;
      }

      if (isEat) {
        this.score++;
        setTimeout(() => {
          this.snake.unshift(this.food);
          this.printSnake();
          this.createFood();
        }, this.speed);

      }
    },

    isDead() {
      const head = this.snake[0];
      if (head.x < 0 || head.x > 19 || head.y < 0 || head.y > 19) {
        this.isOver = true;
        console.log("撞墙！");
        this.$message({
          message: '撞墙！',
          type: 'error'
        });
        return;
      }
      for (let i = 1; i < this.snake.length; i++) {
        if (head.x === this.snake[i].x && head.y === this.snake[i].y) {
          this.isOver = true;
          console.log("撞自己！");
          this.$message({
            message: '游戏结束, 撞到自己了',
            type: 'error'
          });
          return;
        }
      }
    },

    createFood() {
      const x = Math.floor(Math.random() * 20);
      const y = Math.floor(Math.random() * 20);
      for (let i = 0; i < this.snake.length; i++) {
        if (x === this.snake[i].x && y === this.snake[i].y) {
          this.createFood();
          return;
        }
      }
      this.food = {x: x, y: y};
      console.log(this.food);
    },

    keydown(e) {
      switch (e.keyCode) {
        case 37:
          if (this.direction !== 'right') {
            this.direction = 'left';
            console.log('left');
          }
          break;
        case 38:
          if (this.direction !== 'down') {
            this.direction = 'up';
            console.log('up');
          }
          break;
        case 39:
          if (this.direction !== 'left') {
            this.direction = 'right';
            console.log('right');
          }
          break;
        case 40:
          if (this.direction !== 'up') {
            this.direction = 'down';
            console.log('down');
          }
          break;
      }
      this.isEat();
      this.printSnake();
    },
  },
  mounted() {
    document.addEventListener('keydown', this.keydown);
  },
  beforeDestroy() {
    document.removeEventListener('keydown', this.keydown);
  }

}
</script>

<style scoped lang="scss">

  #body{
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }

  #main{
    width: 500px;
    height: 400px;
    border: 1px solid black;

    display: flex;
    flex-direction: row;
  }

  #score{
    width: 100px;
    height: 400px;
    border: 1px solid black;
  }

  #game{
    width: 400px;
    height: 400px;
    border: 1px solid black;

    position:relative;
  }


</style>